# 输入年龄，年龄小于3岁大于0岁的，打印两次儿歌，超过3岁小于5岁的打印一次儿歌
"""age = int(input("请输入你的年龄："))
if age>=0 and age<3:
    for i in range(3):
        print("小兔子乖乖")
        print("把门开开")
        print("快点儿开开")
        print("我要进来")
elif 5>age>=3:
    print("小兔子乖乖")
    print("把门开开")
    print("快点儿开开")
    print("我要进来")"""
# 上述的代码比较冗余，啰嗦 ，而且不容易维护
# 可以使用函数来写一下，下面这个函数，就相当于自定义了一个方法：erge

# def 是函数命名的关键字
def erge():
    age = int(input("请输入你的年龄："))
    if age >= 0 and age < 3:
        for i in range(3):
            print("小兔子乖乖")
            print("把门开开")
            print("快点儿开开")
            print("我要进来")
    elif 5 > age >= 3:
        print("小兔子乖乖")
        print("把门开开")
        print("快点儿开开")
        print("我要进来")
# 没有调用，就不会被执行
# erge()
"""
调用函数，会执行里面的代码
函数调用：
函数的名称+() 就可以
比如：
erge()
"""

# 内置函数
"""str_obj = "aabbcc"
print(len(str_obj)) # len就是内置函数的一种，返回的是字符串的长度
print(list(str_obj)) # list 是内置函数的一种，可以把当前类型强制转化成列表"""

# 标准库函数 json,random 需要导入模块才可以使用的
"""
json：json.dumps() 把字典转换成json对象
      json.loads()   把json对象转换成字典
random:   random.randint()    给定范围，随机返回一个数字
          random.choice()    给定一个序列，随机返回一个
"""
"""import random
print(random.randint(0,9)) # 从0~9随机返回一个数字"""

# 第一个函数
def text():
    """
    函数定义的关键字是：def
    函数名称不能是关键字命名：text()
    """
    print("小兔子乖乖")
    print("把门开开")
    print("快点儿开开")
    print("我要进来")
# 调用函数
# text()
"""age = int(input("请输入你的年龄："))
if age >= 0 and age < 3:
    for i in range(3):
        text()
elif 3 <= age < 5:
    text()"""

# 第一种形态的函数：没有参数传递，也没有返回值
def student_info():
    """
    没有参数传递，也没有返回值的函数
    """
    print(f"沁创测试培训第一期开始：{'王琳琳'}、{'王琳琳1号'}、{'王琳琳2号'}、{'王琳琳3号'}、{'王琳琳4号'}")
    print(f"沁创测试培训第二期开始：{'好健康'}、{'好健康'}、{'好健康'}、{'好健康'}、{'好健康'}")
# 调用函数
# student_info()
"""
沁创测试培训第一期开始：王琳琳、王琳琳1号、王琳琳2号、王琳琳3号、王琳琳4号
沁创测试培训第二期开始：好健康、好健康、好健康、好健康、好健康
"""
# 为什么说没有返回值呢？
# r = student_info() # 用r来接收一下
# print(r) # None 因为没有返回值，所以返回None
# print(student_info())
"""
沁创测试培训第一期开始：王琳琳、王琳琳1号、王琳琳2号、王琳琳3号、王琳琳4号
沁创测试培训第二期开始：好健康、好健康、好健康、好健康、好健康
None
"""

"""lidt1 = [1,2,3]
r = lidt1.pop(0)
print(r) # r 就是被删除的对象，这种就说明有返回值
r1 = lidt1.remove(2)
print(r1) # None 说明这个函数它没有返回值"""

# 第二种形态的函数，没有参数传递，有返回值
def student_info2():
    """
    return:
    这个就是函数的返回值，可以通过变量赋值来接收返回值
    代码执行到return后续就不会再执行了，函数到此结束
    """
    print("沈腾")
    return "沁创测试培训第一期：好健康、好成功、好身体、好营养、好玩\n沁创测试培训第二期：王姐、王琳琳、琳姐、社会琳"
# student_info2()
# r = student_info2()
# print(r)
def student_info2_p():

    return 5+5
    print("5+5的值是：10")

    # 这句话就不会出现的，因为这个print在return的后面，出现return代码到此结束
# student_info2_p()
def student_info2_p1():
    """
    它最终也会只执行一次return
    :return: 返回的是对天气的结果
    """
    a = input("请输入数字:")
    if a == "1":
        return "今天天气很好"
    else:
        return "今天天气不好"
# print(student_info2_p1()) # 有返回值的这种，你要用到就可以使用变量接收或者直接就打印输出：

# 第三种形态的函数：用参数传递，没有返回值
def student_info3(name:str):
    """
    str:提醒程序员，这个函数的传参类型是字符串
    :param name: 传递学生的花名，name就是形参,形式参数
    :return: None
    """
    if name == "好健康":
        print("郝健成")
    elif name == "琳姐":
        print("琳琳")
    elif name == '丁':
        print("丁丁")
    elif name == "欣":
        print("xinxin")
# student_info3("好健康")
# student_info3(11) # 传参的类型有问题，因为函数定义的传参类型是字符串

# 第四种形态的函数：有形参，有返回值
def student_info4(name:str)->str:
    """
    ->str:返回的内容类型是字符串格式的
    :param name: 要传递的学生名花名
    :return: 返回的是学生名字
    """
    if name == "好健康":
        return "郝健成"
    elif name == "琳姐":
        return "社会琳"
    elif name == "可欣":
        return "可欣"
    else:
        return "姓名不存在"
# print(student_info4("琳姐")) # 打印就会用到return里面内容了

def student_info5(name="沈腾"): # 默认传参值，不传就用这个参数
    """
    name = "沈腾"，就是默认值，什么都不传入的话，就是传的这个参数
    :param name:
    :return:
    """
    if name=="好健康":
        return "郝健成"
    elif name=="沈腾":
        return "马丽"
    elif name=="可欣":
        return "可欣"
    else:
        return "姓名不存在"
# print(student_info5()) # 什么都不写，默认name是沈腾，返回马丽
def student_info6(name,age,address,phone_number,sex):
    return f"大家好，我叫{name},今年{age}岁,地址是{address},手机号码是{phone_number},性别是{sex}"
# 默认按照参数定义好的顺序，去传参
# print(student_info6("好健康", "99", "吉林吉林", "12134423", "女"))
# 打乱顺序进行传参，一定要把参数名称写上去，后面跟上参数才可以
# print(student_info6(name="好健康",age=19,phone_number=1231312,address="辽宁沈阳",sex="女"))
def student_info7(name="好健康",age=19,phone_number=110101,address="沈阳",sex="男"):
    """
    在定义默认值参数的时候，都要放到最后面，不要和普通的形参顺序打乱，不然会报错
    def student_info7(name,age,address="沈阳",phone_number,sex="男")  这种方式定义就是错误的
    :param name: 学生姓名
    :param age: 年龄
    :param address:家庭地址
    :param phone_number: 手机号码
    :param sex: 性别
    :return:
    """
    return f"大家好，我叫：{name}，今年：{age}岁，地址是：{address}，手机号码是：{phone_number}，性别是：{sex}"

def student_info8(*args):
    """
    :param args: 不定长接收参数，返回值是一个元组
    :return:
    """
    print(args)
# todo:不定长参数，不限制参数的长度，可以传任意的，也不限制类型
# student_info8("好健康",19,"吉林吉林",[10,20,30],(1,2,3),{"name":"好健康"})

# 要注意，不定长参数和位置参数在定义的时候，一定要把不定长的放在最后
def student_info9(age,name,*args):
    print(age)
    print(name)
    print(args)
# student_info9(19,"好健康",[12,2,2,3,4],"34424e")

# todo:不定长关键字参数
def student_info11(**kwargs):
    """
    :param kwargs: 不定长关键字参数，返回值是字典
    :return:
    """
    print(kwargs)
# student_info11(name="郝建成",age=18,sex="男")

# 既有普通，还有不定长参数，不定长关键字参数
def student_info12(name,age,*args,**kwargs):
    """
    定义的顺序，先是位置参数，后是不定长参数，最后是不定长关键字参数
    :param name:
    :param age:
    :param args:
    :param kwargs:
    :return:
    """
    print(name)
    print(age)
    print(args)
    print(kwargs)
# student_info12("好健康",19,[12,23,43.453],"12324234",name1="号建成",age1=19)

# 函数的作用域
a = 100
word = "hello"
x = 1000
def text1():
    """
    函数体里面的变量，叫做局部变量
    当你访问函数的时候，局部变量>全局变量
    :return:
    """
    x = "hello"
    print("x = {}".format(x))
    a = 10
    print("a = {}".format(a))
# text1()

# 我想要改变全局变量
a2 = 10
b2 = 20
def text3():
    global a2,b2  # global关键字，引用全局变量
    a2 = "好健康" # 修改了全局变量 a2 为 好健康
    b2 = "社会丁" # 修改了全局变量 b2 为 社会丁
    print(a2)
    print(b2)
text3()
"""
好健康
社会丁
"""